package cn.com.yang.egg;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtField;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.Modifier;
import javassist.NotFoundException;

/**
 * 
 * TODO 对象处理工具
 * @author yangyijin
 * @date 2023年2月11日-下午11:43:05
 */
public class JavassistMain {
	
	public static void main(String[] args) throws 
		CannotCompileException, 
		NotFoundException, 
		IOException, 
		InstantiationException, 
		IllegalAccessException, 
		NoSuchMethodException, 
		SecurityException, 
		IllegalArgumentException, InvocationTargetException {
		
		ClassPool cpClassPool = ClassPool.getDefault();
		CtClass clazz = cpClassPool.makeClass("cn.com.yang.JavassitTest");
		
		// 创建字段，指定字段类型、字段名称、字段所属分类
		CtField field = new CtField(cpClassPool.get("java.lang.String"), "prop",clazz);
		// 指定该字段使用private修饰
		field.setModifiers(Modifier.PRIVATE);
		//设置prop字段的setter、getter
		clazz.addMethod(CtNewMethod.setter("setProp", field));
		clazz.addMethod(CtNewMethod.getter("getProp", field));
		//设置prop字段的初始化值，并且将prop字段添加到clazz中
		clazz.addField(field, CtField.Initializer.constant("MyName"));
		//创建构造方法，指定了构造方法的参数类型和构造方法所属的类
		CtConstructor ctConstructor = new CtConstructor(new CtClass[] {}, clazz);
		//设置方法体
		StringBuffer bodyBuffer = new StringBuffer();
		bodyBuffer.append("{\n prop=\"MyName\";\n}");
		ctConstructor.setBody(bodyBuffer.toString());
		//将构造方法添加到clazz中
		clazz.addConstructor(ctConstructor);
		// 创建execute()方法，指定方法的返回值，方法名称，方法参数列表、以及方法解析所属的类
		CtMethod ctMethod = new CtMethod(CtClass.voidType, "execute", new CtClass[] {},clazz);
		// 指定方法public修饰
		ctMethod.setModifiers(Modifier.PUBLIC);
		// 设置方法体
		bodyBuffer = new StringBuffer();
		bodyBuffer.append("{\n System.out.println(\"execute():\"+this.prop);}");
		bodyBuffer.append("\n");
		ctMethod.setBody(bodyBuffer.toString());
		clazz.addMethod(ctMethod); //将execute()方法添加到clazz中
		clazz.writeFile("D://");//将上面定义的JavassistTest类保存到指定的目录
		//加载clazz类，并创建对象
		Class<?> clz = clazz.toClass();
		Object object = clz.newInstance();
//		Object object = clz.getDeclaredConstructor().newInstance(null);
		
		// 调用execute()方法
		java.lang.reflect.Method method = object.getClass().getMethod("execute()", new Class[] {});
		method.invoke(object, new Object[] {});
	}

}
